/*
    Geocache: some utilities for managing and visualizing geocache information
    Copyright (C) 2008  Gary Jackson

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * Fetch.java
 */

package com.thegbomb.geocache;

import com.thegbomb.common.CommandLine;
import com.thegbomb.common.CommandLine.Action;
import com.thegbomb.common.CommandLine.UsageException;
import com.thegbomb.common.MapIterator;
import com.thegbomb.common.MessageCollection;
import java.io.File;
import java.util.Iterator;
import java.util.Properties;
import java.util.regex.Pattern;
import java.util.zip.ZipInputStream;
import javax.mail.Message;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.URLName;
import javax.mail.search.AndTerm;
import javax.mail.search.NotTerm;
import javax.mail.search.OrTerm;
import javax.mail.search.SearchTerm;
import javax.mail.search.SubjectTerm;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;

/**
 *
 * @author Gary Jackson
 */
public class Fetch {
    static private Logger logger = Logger.getLogger(Fetch.class);
    static private final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
    
    static private SearchTerm knownTerm = new OrTerm(
            new SubjectTerm("[GEO] Pocket Query: My Finds Pocket Query"), 
            new SubjectTerm("[GEO] Pocket Query: My Hides Pocket Query"));
    static private SearchTerm unknownTerm = new AndTerm(new SubjectTerm("[GEO] Pocket Query: "), new NotTerm(knownTerm));

    static private String name = "";
    static private String password = "";
    static private File   output = new File(".");
    static private SearchTerm term = unknownTerm;
    /**
     * Run the Fetch program.
     * @param args the command line arguments
     */
    public static void main(String[] args) throws Exception {
        BasicConfigurator.configure();
        
        CommandLine command = new CommandLine(false);
        command.addAction("name", new Action(){
            public void act(String option, String argument) { name = argument; }
            public boolean isArgument() { return true; }
            public boolean isMultiplicity() { return false; }
            public boolean isRequired() { return true; }
        });
        command.addAction("pass", new Action(){
            public void act(String option, String argument) { password = argument; }
            public boolean isArgument() { return true; }
            public boolean isMultiplicity() { return false; }
            public boolean isRequired() { return true; }
        });
        command.addAction("outdir", new Action(){
            public void act(String option, String argument) throws UsageException {
                File dir = new File(argument);
                if (!dir.isDirectory())
                    throw new UsageException("argument " + argument + " must be a directory");
                output = dir;
            }
            public boolean isArgument() { return true; }
            public boolean isMultiplicity() { return false; }
            public boolean isRequired() { return false; }
        });
        command.addAction("known", new Action(){
            public void act(String option, String argument) throws UsageException {
                term = knownTerm;
            }
            public boolean isArgument() { return false; }
            public boolean isMultiplicity() { return false; }
            public boolean isRequired() { return false; }
        });
        command.addAction("unknown", new Action(){
            public void act(String option, String argument) throws UsageException {
                term = unknownTerm;
            }
            public boolean isArgument() { return false; }
            public boolean isMultiplicity() { return false; }
            public boolean isRequired() { return false; }
        });
        
        try {
            command.process(args);
        } catch (UsageException e) {
            command.printUsage(System.err, Fetch.class.getName(), e);
            return;
        }
        
        Properties props = new Properties();
        
        props.setProperty("mail.pop3.socketFactory.class", SSL_FACTORY);
        props.setProperty("mail.pop3.socketFactory.fallback", "false");
        props.setProperty("mail.pop3.port", "995");
        props.setProperty("mail.pop3.socketFactory.port", "995");
        
        Session session = Session.getDefaultInstance(props, null);
        
        URLName urln = new URLName("pop3", "pop.gmail.com", 995, null, name, password);
        
        MessageCollection collection = new MessageCollection(session, urln, term);
        
        Pattern zipMimeType = Pattern.compile("^(application|multipart)/(x-|)zip(|-compressed);.*",
                Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
        Iterator<Part> m2p = new MapIterator<Message, Part>(collection.iterator(), new MessageToParts(zipMimeType));
        
        Iterator<ZipInputStream> p2zs = new MapIterator<Part, ZipInputStream>(m2p, new PartToZipStreams());
        
        Pattern fileNamePattern = Pattern.compile(".*\\.gpx$");
        Iterator<File> zs2f = new MapIterator<ZipInputStream, File>(p2zs, new ZipStreamToFiles(fileNamePattern, output));
        
        while (zs2f.hasNext()) {
            File f = zs2f.next();
            logger.info("fetched file: " + f.getCanonicalPath());
        }
        
        collection.close();
    }
}
